// This File is part of the "GmailNotifier2" Project
// 
// Copyright  2009 sometmes@gmail.com
// All rights reserved
// 
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

using System;
using System.Collections.Generic;
using System.Windows.Forms;

using System.Threading;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Ipc;
using System.IO;
using System.Diagnostics;
using Microsoft.Win32;

namespace Notify2
{
    static class Program
    {
        internal static OptionsForm OptionsForm;
        internal static SendMailForm SendMailForm;

        static Mutex ownerMutex;
        internal static Mutex sequenceMutex;

        static SetupForm setupForm;

        static bool stayInTray; // Program is started with /tray or no parameters
        static public bool StayInTray
        {
            get { return stayInTray; }
            set { stayInTray = value; }
        }

        static private bool startup; // Program is started with no parameters, usually first time use.
        static public bool Startup
        {
            get { return startup; }
            set { startup = value; }
        }

        static private bool firstInstance;

        public static bool FirstInstance
        {
            get { return Program.firstInstance; }
            set { Program.firstInstance = value; }
        }

        static void Run(Form frm)
        {
            Application.ApplicationExit += new EventHandler(Application_ApplicationExit);
            Application.Run(frm);
        }

        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            string[] args = Environment.GetCommandLineArgs();
            string temp = Environment.GetEnvironmentVariable("TEMP");

            if (args.Length > 1 && args[1].ToLower() == "/uninstall")
            {
                Run(new SetupUninstallForm());
                return;
            }
            if (Path.GetFileNameWithoutExtension(Application.ExecutablePath).ToLower() == "uninstall"
                ||
                (args.Length > 1 && args[1].ToLower() == "/uninstallprepare")
                )
            {
                string uninstall = Path.Combine(temp, "uninstall.exe");
                SetupUtils.Copy(Application.ExecutablePath, uninstall);
                ScheduleDeleteUninstallOnReboot(uninstall);
                ProcessStartInfo processStartInfo = new ProcessStartInfo(uninstall);
                processStartInfo.Verb = "runas";
                processStartInfo.UseShellExecute = true;
                processStartInfo.ErrorDialog = true;
                processStartInfo.WorkingDirectory = Path.GetDirectoryName(uninstall);
                processStartInfo.Arguments = "/uninstall";
                Process.Start(processStartInfo);
                return;
            }

            if (!Properties.Settings.Default.SetupExecuted)
            {
                setupForm = new SetupForm();
                Run(setupForm);
                if (!setupForm.RunWithoutInstall)
                {
                    Application.Exit();
                    return;
                }
            }

            if (args.Length == 1 || args[1].ToLower() == "/tray")
            {
                Program.ownerMutex = new Mutex(true, "Local\\GmailNotifier2" + Properties.Settings.Default.Color
                    , out Program.firstInstance);
                Program.stayInTray = true;
                if (Program.firstInstance)
                {
                    //if (args.Length == 1) 
                        Program.Startup = true;
                    Run(new NotifierTrayHiddenForm());
                }
                else
                {
                    return; // We already have tray icon running.
                }

            }
            else if (args[1].ToLower() == "/send")
            {
                bool yourTurn;
                Program.sequenceMutex = new Mutex(true, "Local\\SendToGmail2Sequence" + Properties.Settings.Default.Color
                    , out yourTurn);
                if (!yourTurn)
                    sequenceMutex.WaitOne();

                Program.ownerMutex = new Mutex(true, "Local\\GmailNotifier2" + Properties.Settings.Default.Color
                    , out Program.firstInstance);
                Program.stayInTray = false;
                Program.Startup = false; 
                if (Program.firstInstance)
                {
                    Run(new NotifierTrayHiddenForm()); // OnLoad = RegisterSingleInstanceChannelAndController
                }
                else
                {
                    IpcClientChannel clientChannel = new IpcClientChannel();
                    ChannelServices.RegisterChannel(clientChannel, false);

                    SingleInstanceController singleInstanceForm = (SingleInstanceController)Activator.GetObject(typeof(SingleInstanceController),
                      "ipc://SendToGmail2" + Properties.Settings.Default.Color + "/FirstInstance");

                    if (!singleInstanceForm.Equals(null))
                    {
                        if (args.Length > 2)
                            singleInstanceForm.AddFileAsync(args[2]);
                        sequenceMutex.ReleaseMutex();
                    }
                    else
                    {
                        sequenceMutex.ReleaseMutex(); 
                        throw new SystemException("IPC Server not found");
                    }
                }
            }
        }

        public static void ScheduleDeleteUninstallOnReboot(string path)
        {
            RegistryKey key;
            using (key = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\RunOnce", true))
            {
                key.SetValue("GmailNotifier2Cleanup", "cmd /C del " + path + " && @echo GmailNotifier2 Cleanup completed. && pause");
            }
        }

        internal static SingleInstanceController RegisterSingleInstanceChannelAndController(SendMailForm mainForm)
        {
            IpcServerChannel serverChannel = new IpcServerChannel("SendToGmail2" + Properties.Settings.Default.Color);
            ChannelServices.RegisterChannel(serverChannel, false);
            SingleInstanceController singleInstanceController = new SingleInstanceController(mainForm);
            RemotingServices.Marshal(singleInstanceController, "FirstInstance");
            return singleInstanceController;
        }

        static void Application_ApplicationExit(object sender, EventArgs e)
        {
            if (Program.stayInTray)
                Properties.Settings.Default.Save();
        }
    }
}
















